﻿using System;
using System.Globalization;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using UFIDA.U9.Cust.Pub.WS.ProxyService.Json;
using UFIDA.U9.WSS.ProxyService.Utils;

namespace UFIDA.U9.WSS.ProxyService.Json
{
    /// <summary>
    ///     Json 帮助类
    /// </summary>
    public static class JsonHelper
    {
        private const string DefaultDateTimeFormat = "yyyy-MM-dd HH:mm:ss";
        private const DateTimeStyles DefaultDateTimeStyles = DateTimeStyles.AssumeLocal;
        private const Formatting DefaulResponeJsonFormatting = Formatting.None;

        /// <summary>
        ///     获取Json序列化配置
        /// </summary>
        /// <returns></returns>
        public static JsonSerializerSettings GetJsonSerializerSettings(IContractResolver resolver)
        {
            JsonSerializerSettings settings = new JsonSerializerSettings();
            settings.ContractResolver = resolver;
            settings.MissingMemberHandling = MissingMemberHandling.Ignore;
            settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            string dateTimeFormat = ConfigurationHelper.GetAppSettingValue(Constant.DateTimeFormatName);
            DateTimeStyles dateTimeStyles = DefaultDateTimeStyles;
            string strDateTimeStyles = ConfigurationHelper.GetAppSettingValue(Constant.DateTimeStylesName);
            if (!string.IsNullOrEmpty(strDateTimeStyles))
                Enum.TryParse(strDateTimeStyles, out dateTimeStyles);
            settings.Converters.Add(new IsoDateTimeConverter
            {
                DateTimeFormat = string.IsNullOrEmpty(dateTimeFormat) ? DefaultDateTimeFormat : dateTimeFormat,
                DateTimeStyles = dateTimeStyles
            });
            return settings;
        }

        /// <summary>
        ///     获取JsonSerializer
        /// </summary>
        /// <param name="resolver"></param>
        /// <returns></returns>
        public static JsonSerializer GetJsonSerializer(IContractResolver resolver)
        {
            JsonSerializer serializer = new JsonSerializer();
            serializer.ContractResolver = resolver;
            serializer.MissingMemberHandling = MissingMemberHandling.Ignore;
            serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            string dateTimeFormat = ConfigurationHelper.GetAppSettingValue(Constant.DateTimeFormatName);
            DateTimeStyles dateTimeStyles = DefaultDateTimeStyles;
            string strDateTimeStyles = ConfigurationHelper.GetAppSettingValue(Constant.DateTimeStylesName);
            if (!string.IsNullOrEmpty(strDateTimeStyles))
                Enum.TryParse(strDateTimeStyles, out dateTimeStyles);
            serializer.Converters.Add(new IsoDateTimeConverter
            {
                DateTimeFormat = string.IsNullOrEmpty(dateTimeFormat) ? DefaultDateTimeFormat : dateTimeFormat,
                DateTimeStyles = dateTimeStyles
            });
            return serializer;
        }

        /// <summary>
        ///     获取默认JsonSerializer
        /// </summary>
        /// <returns></returns>
        public static JsonSerializer GetDefaultJsonSerializer()
        {
            return GetJsonSerializer(new BaseContractResolver());
        }

        /// <summary>
        ///     获取返回JsonBody
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="resolver"></param>
        /// <returns></returns>
        public static byte[] GetReturnJsonBody(object obj, IContractResolver resolver = null)
        {
            byte[] body;
            if (resolver == null)
                resolver = new BaseContractResolver();
            JsonSerializer serializer = GetJsonSerializer(resolver);
            string strReturnJsonNoStartsWithBOM =
                ConfigurationHelper.GetAppSettingValue(Constant.ResponeJsonNoStartsWithBOMName);
            bool returnJsonNoStartsWithBOM = !string.IsNullOrEmpty(strReturnJsonNoStartsWithBOM) &&
                                             strReturnJsonNoStartsWithBOM.ToLower() == "true";
            string returnJsonFormatting =
                ConfigurationHelper.GetAppSettingValue(Constant.ResponeJsonFormattingName);
            using (MemoryStream ms = new MemoryStream())
            {
                using (StreamWriter sw = new StreamWriter(ms, new UTF8Encoding(returnJsonNoStartsWithBOM)))
                {
                    using (JsonWriter writer = new JsonTextWriter(sw))
                    {
                        writer.Formatting = !string.IsNullOrEmpty(returnJsonFormatting) &&
                                            returnJsonFormatting.ToLower() == "indented"
                            ? Formatting.Indented
                            : DefaulResponeJsonFormatting;
                        serializer.Serialize(writer, obj);
                        sw.Flush();
                        body = ms.ToArray();
                        writer.Close();
                    }

                    sw.Close();
                }

                ms.Close();
            }

            return body;
        }

        /// <summary>
        ///     对象转为Json
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="resolver"></param>
        /// <returns></returns>
        public static string ToJson(object obj, IContractResolver resolver = null)
        {
            if (obj == null) return string.Empty;
            if (resolver == null)
                resolver = new BaseContractResolver();
            JsonSerializerSettings settings = GetJsonSerializerSettings(resolver);
            return JsonConvert.SerializeObject(obj, Formatting.None, settings);
        }

        /// <summary>
        ///     Json转为对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="jsonString"></param>
        /// <param name="resolver"></param>
        /// <returns></returns>
        public static T FromJson<T>(string jsonString, IContractResolver resolver = null)
        {
            if (resolver == null)
                resolver = new BaseContractResolver();
            JsonSerializerSettings settings = GetJsonSerializerSettings(resolver);
            return JsonConvert.DeserializeObject<T>(jsonString, settings);
        }
    }
}